package com.et114.components.acegi.intercept.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.ConfigAttributeEditor;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.acegisecurity.GrantedAuthorityImpl;

import com.et114.components.acegi.Constants;
import com.et114.components.acegi.cache.AcegiCacheManager;
import com.et114.components.acegi.resourcedetails.ResourceDetails;
import com.et114.core.utility.StringPool;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author guanhw
 */
public class DBFilterInvocationDefinitionSource extends AbstractFilterInvocationDefinitionSource {
	private static final Log		logger									= LogFactory.getLog( DBFilterInvocationDefinitionSource.class );
	private boolean					convertUrlToLowercaseBeforeComparison	= false;
	private boolean					useAntPath								= false;
	private final PathMatcher		pathMatcher								= new AntPathMatcher();
	private final PatternMatcher	matcher									= new Perl5Matcher();
	private AcegiCacheManager		acegiCacheManager;
	private List								excludesURI				= new ArrayList ( 0 );

	public void setAcegiCacheManager ( AcegiCacheManager acegiCacheManager ) {
		this.acegiCacheManager = acegiCacheManager;
	}

	

	
	/**
	 * 返回当前URL对应的ROLE
	 * @see org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource#lookupAttributes(java.lang.String)
	 */
	public ConfigAttributeDefinition lookupAttributes ( String url ) {
		try {
			List urls  = acegiCacheManager.getComponents ( ) ; 
			urls.addAll ( acegiCacheManager.getUrlResStrings() ) ;
			// 倒叙排序
			Collections.sort( urls );
			Collections.reverse( urls );
			if ( convertUrlToLowercaseBeforeComparison ) {
				url = url.toLowerCase();
			}
			
			String tmp  = url.toLowerCase ( ) ; 
			for ( java.util.Iterator iter = excludesURI.iterator ( ) ; iter.hasNext ( ) ;  ) {
				String exs = iter.next ( ).toString ( ).toLowerCase ( ) ; 
				if ( pathMatcher.match ( exs , tmp ) ) {
					return null ;
				}
			}    	

			
			
			
			GrantedAuthority [ ] authorities = new GrantedAuthority [ 0 ];
			
			//@since  v1.11
			if ( authorities.length == 0  ) {
				for ( Iterator iterator = urls.iterator(); iterator.hasNext(); ) {
					String resString = ( String ) iterator.next();
					java.util.StringTokenizer sts = new java.util.StringTokenizer( resString , Constants.URL_RESOURCES_SPLIT ) ;
					int count = sts.countTokens ( ) ; 
					boolean  matched = false ;
					for ( int i = 0 ; i < count ; i ++  ) {
						String rs = sts.nextToken ( ) ; 
						if ( isUseAntPath() ) {
							if ( rs .indexOf ( StringPool.COLON ) > 0 ) {
								rs = rs.substring ( rs.indexOf ( StringPool.COLON  ) + 1 , rs.length ( ) ) ; 
							}
							
							matched = pathMatcher.match( rs , url );
							
						} else {
							Pattern compiledPattern = null;
							Perl5Compiler compiler = new Perl5Compiler();
							try {
								compiledPattern = compiler.compile( rs , Perl5Compiler.READ_ONLY_MASK );
							} catch ( Exception mpe ) {
								logger.error( mpe.getMessage(), mpe );
							}
							matched = matcher.matches( url, compiledPattern );
						}
	
					
						if ( matched ) {
							ResourceDetails rd = acegiCacheManager.getAuthorityFromCache( resString );
							authorities = rd.getAuthorities();
							break;
						}					
					}
					
					if ( matched ) break ;
				}

			}
			
			
			
			/*
			if ( authorities.length == 0  ) {
				authorities = new GrantedAuthority [ 1 ];
				authorities[0] = new GrantedAuthorityImpl( Constants.VOTER_USER_PREFIX ) ;				
			} */
			
			if ( authorities.length > 0 ) {
					String authoritiesStr = " ";
					for ( int i = 0; i < authorities.length; i++ ) {
						authoritiesStr += authorities [ i ].getAuthority() + ",";
					}
					String authStr = authoritiesStr.substring( 0, authoritiesStr.length() - 1 );
					ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
					configAttrEditor.setAsText( authStr.trim() );
					return ( ConfigAttributeDefinition ) configAttrEditor.getValue();
			}

		} catch ( Exception e ) {
			logger.error( e.getMessage(), e );
		}
		return null;
	}

	public Iterator getConfigAttributeDefinitions ( ) {
		return null;
	}

	public void setConvertUrlToLowercaseBeforeComparison (
			boolean convertUrlToLowercaseBeforeComparison ) {
		this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
	}

	public boolean isConvertUrlToLowercaseBeforeComparison ( ) {
		return convertUrlToLowercaseBeforeComparison;
	}

	public boolean isUseAntPath ( ) {
		return useAntPath;
	}

	public void setUseAntPath ( boolean useAntPath ) {
		this.useAntPath = useAntPath;
	}

	public List getExcludesURI ( ) {
		return excludesURI;
	}




	public void setExcludesURI ( List excludesURI ) {
		this.excludesURI = excludesURI;
	}




	public static void main( String[] ss ) {
		 PathMatcher		pathMatcher								= new AntPathMatcher();
		 boolean match = pathMatcher.match ( "/**/*method*4View*" , "/pro/cellPhone.go?method=getCellPhones4View" ) ;
		 logger.info ( "match/." + match ) ;
	}

}
